package com.hongmeng.teamwork.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Preconditions;
import com.google.common.net.HttpHeaders;
import com.hongmeng.teamwork.config.FeishuProperties;
import com.hongmeng.teamwork.entity.auth.AppAccessToken;
import com.hongmeng.teamwork.entity.auth.TenantAccessToken;
import com.hongmeng.teamwork.entity.base.Result;
import com.hongmeng.teamwork.utils.JwtUtil;
import com.hongmeng.teamwork.utils.RSAUtil;
import com.lark.oapi.Client;
import com.lark.oapi.core.request.RequestOptions;
import com.lark.oapi.core.utils.Lists;
import com.lark.oapi.service.auth.v3.model.*;
import com.lark.oapi.service.authen.v1.model.CreateAccessTokenReq;
import com.lark.oapi.service.authen.v1.model.CreateAccessTokenReqBody;
import com.lark.oapi.service.authen.v1.model.CreateAccessTokenResp;
import lombok.extern.log4j.Log4j2;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Log4j2
@RestController
@RequestMapping("/auth")
public class AuthController {

    @Resource
    private Client client;
    @Resource
    private FeishuProperties feishuProperties;

    @GetMapping("/getTenantAccessToken")
    public Result<?> getTenantAccessToken() {
        try {
            InternalTenantAccessTokenResp resp = client.auth().tenantAccessToken()
                    .internal(InternalTenantAccessTokenReq.newBuilder()
                            .internalTenantAccessTokenReqBody(
                                    InternalTenantAccessTokenReqBody.newBuilder()
                                            .appId(feishuProperties.getAppId())
                                            .appSecret(feishuProperties.getAppSecret())
                                            .build())
                            .build());
            TenantAccessToken tenantAccessToken = JSONObject.parseObject(new String(resp.getRawResponse().getBody(), StandardCharsets.UTF_8), TenantAccessToken.class);
            if (log.isInfoEnabled()) {
                log.info("AuthController.getAppAccessToken.appAccessToken: {}", JSON.toJSONString(tenantAccessToken));
            }
            return Result.ok(tenantAccessToken.getTenantAccessToken());
        } catch (Exception e) {
            log.error("AuthController.getAppAccessToken.error: {}", e.getMessage(), e);
            return Result.fail("获取 app_access_token 失败！");
        }
    }

    @GetMapping("/getUserAccessToken")
    public Result<?> getUserAccessToken(@RequestParam("authCode") String authCode) {
        try {
            Map<String, List<String>> headers = new HashMap<>();
            headers.put(HttpHeaders.AUTHORIZATION, Lists.newArrayList(getAppAccessToken()));
            CreateAccessTokenResp resp = client.authen().accessToken()
                    .create(CreateAccessTokenReq.newBuilder()
                            .createAccessTokenReqBody(CreateAccessTokenReqBody.newBuilder()
                                    .grantType("authorization_code")
                                    .code(authCode)
                                    .build())
                                    .build(),
                            RequestOptions.newBuilder()
                                    .headers(headers).build());
            if (log.isInfoEnabled()) {
                log.info("AuthController.getUserAccessToken.userAccessToken: {}", JSON.toJSONString(resp.getData()));
            }
            Preconditions.checkNotNull(resp.getData(), resp.getError());
            return Result.ok(resp.getData());
        } catch (Exception e) {
            log.error("AuthController.getUserAccessToken.error: {}", e.getMessage(), e);
            return Result.fail("获取 user_access_token 失败！");
        }
    }

    public String getAppAccessToken() {
        try {
            InternalAppAccessTokenResp resp = client.auth().appAccessToken()
                    .internal(InternalAppAccessTokenReq.newBuilder()
                            .internalAppAccessTokenReqBody(InternalAppAccessTokenReqBody.newBuilder()
                                    .appId(feishuProperties.getAppId())
                                    .appSecret(feishuProperties.getAppSecret())
                                    .build())
                            .build());
            AppAccessToken appAccessToken = JSONObject.parseObject(new String(resp.getRawResponse().getBody(), StandardCharsets.UTF_8), AppAccessToken.class);
            if (log.isInfoEnabled()) {
                log.info("AuthController.getAppAccessToken.appAccessToken: {}", JSON.toJSONString(appAccessToken));
            }
            return appAccessToken.getAppAccessToken();
        } catch (Exception e) {
            log.error("AuthController.getAppAccessToken.error: {}", e.getMessage(), e);
            throw new RuntimeException("获取 app_access_token 失败！");
        }
    }

    @GetMapping("/appId")
    public Result<?> appId() {
        String encryptAppId = RSAUtil.encrypt(feishuProperties.getAppId());
        if (log.isInfoEnabled()) {
            log.info("appId.encryptAppId: {}", encryptAppId);
        }
        return Result.ok(encryptAppId);
    }
}
